package com.hm.oauth.web;

import java.net.URI;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.oltu.oauth2.as.issuer.MD5Generator;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth2.common.message.types.ResponseType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.hm.common.common.CommonUtil;
import com.hm.common.exception.ServiceException;
import com.hm.common.model.ResultMessage;
import com.hm.oauth.def.OauthDef;
import com.hm.oauth.service.AuthorizeService;
import com.hm.oauth.service.ClientService;
import com.hm.oauth.service.UserService;
import com.hm.oauth.vo.UserVo;

/**
 * @author shishun.wang
 * @date 下午3:20:23 2016年8月31日
 * @version 1.0
 * @describe
 */
@Controller
@SuppressWarnings("rawtypes")
public class AuthorizeController {

	@Autowired
	private ClientService clientService;

	@Autowired
	private UserService userService;

	@Autowired
	private AuthorizeService authorizeService;

	@SuppressWarnings("unchecked")
	@RequestMapping(value = "authorize", method = RequestMethod.GET)
	public @ResponseBody Object authorize(HttpServletRequest request, Model model) {
		String redirectURI = null;
		try {
			OAuthAuthzRequest authzRequest = new OAuthAuthzRequest(request);

			String clientId = authzRequest.getClientId();
			if (CommonUtil.isEmpty(clientService.getClinetByClientId(clientId))) {// 客户端传入id不正确
				OAuthResponse response = OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
						.setError(OAuthError.TokenResponse.INVALID_CLIENT)
						.setErrorDescription(OauthDef.INVALID_CLIENT_ID).buildJSONMessage();
				return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
			}

			// 目前仅支持CODE，另外还有TOKEN
			String responseType = authzRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE);
			// 客户端重定向地址
			redirectURI = authzRequest.getParam(OAuth.OAUTH_REDIRECT_URI);

			// 登陆信息验证
			UserVo userVo = null;
			{
				String username = request.getParameter(OauthDef.LOGIN_USERNAME);
				String password = request.getParameter(OauthDef.LOGIN_PASSWORD);
				if (CommonUtil.isNotEmpty(username, password)) {
					userVo = userService.login(username, password);
				} else {
					throw ServiceException.warn("用户名、密码不能为空");
				}
			}

			// 生成授权码
			String authorizationCode = null;
			if (responseType.equals(ResponseType.CODE.toString())) {
				OAuthIssuerImpl oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());
				authorizationCode = oauthIssuerImpl.authorizationCode();
				authorizeService.put(authorizationCode, userVo.getId());
			}

			// 进行OAuth响应构建
			OAuthASResponse.OAuthAuthorizationResponseBuilder builder = OAuthASResponse.authorizationResponse(request,
					302);
			// 设置授权码
			builder.setCode(authorizationCode);

			// 构建响应
			OAuthResponse response = builder.location(redirectURI).buildQueryMessage();

			// 根据OAuthResponse返回ResponseEntity响应
			HttpHeaders headers = new HttpHeaders();
			headers.setLocation(new URI(response.getLocationUri()));
			return new ResponseEntity(headers, HttpStatus.valueOf(response.getResponseStatus()));
		} catch (Exception e) {
			ResultMessage<Object> resultMessage = new ResultMessage<>();
			{
				resultMessage.setMessage(CommonUtil.isEmpty(redirectURI) ? "验证回调地址不能为空" : e.getMessage());
			}
			ResponseEntity responseEntity = new ResponseEntity<>(resultMessage, HttpStatus.BAD_REQUEST);
			return responseEntity;
		}
	}
}
